#ifndef __MY_SERVER__
#define __MY_SERVER__ 

#include "data.hpp"
#include "util.hpp"
#include "httplib.h"
#include <stdlib.h>

namespace aod 
{
#define WWWROOT "./www"
#define VIDEO_ROOT "/video/"
#define IMAGE_ROOT "/image/"

  TableVideo *tb_video = NULL;
  class Server{
    private:
      int _port;//服务器端口号
      httplib::Server _srv;
    private:
      static void Insert(const httplib::Request &req, httplib::Response &rsp)
      {
        //判断req是否合法
        if(req.has_file("name") == false ||
            req.has_file("info") == false ||
            req.has_file("video") == false ||
            req.has_file("image") == false )
        {
          //请求不合法
          rsp.status = 400;
          rsp.body = R"({"result":false, "reason":上传信息错误})";
          rsp.set_header("Content-Type","application/json");
          return;
        }
        //从req中获取视频相关内容
        httplib::MultipartFormData name = req.get_file_value("name");
        httplib::MultipartFormData info = req.get_file_value("info");
        httplib::MultipartFormData video = req.get_file_value("video");
        httplib::MultipartFormData image = req.get_file_value("image");

        std::string video_name = name.content;
        std::string video_info = info.content;
        std::string video_path;
        video_path += WWWROOT;
        video_path += VIDEO_ROOT;
        video_path += video_name;
        video_path += video.filename;
        std::string image_path;
        image_path += WWWROOT;
        image_path += IMAGE_ROOT;
        image_path += video_name;
        image_path += image.filename;

        //保存文件正文
        if(!FileUtil(video_path).SetContent(video.content))
        {
          //视频文件存储失败
          rsp.status = 500;
          rsp.body = R"({"result":false, "reason":视频文件存储失败})";
          rsp.set_header("Content-Type","application/json");
          return;
        }
        if(!FileUtil(image_path).SetContent(image.content))
        {
          //图片文件存储失败
          rsp.status = 500;
          rsp.body = R"({"result":false, "reason":图片文件存储失败})";
          rsp.set_header("Content-Type","application/json");
          return;
        }
        //添加进数据库
        Json::Value video_json;
        video_json["name"] = video_name;
        video_json["info"] = video_info;
        std::string video_sql_root = VIDEO_ROOT;//数据库中存储的是相对路径
        video_sql_root += video_name;
        video_sql_root += video.filename;
        video_json["video"] = video_sql_root;
        std::string image_sql_root = IMAGE_ROOT;//数据库中存储的是相对路径
        image_sql_root += video_name;
        image_sql_root += image.filename;
        video_json["image"] = image_sql_root;

        if(!tb_video->Insert(video_json))
        {
          //数据库新增数据失败
          rsp.status = 500;
          rsp.body = R"({"result":false, "reason":数据库新增数据失败})";
          rsp.set_header("Content-Type","application/json");
          return;
        }
        return;
      }
      static void Delete(const httplib::Request &req, httplib::Response &rsp)
      {
        //获取视频ID
        int video_id = std::stoi(req.matches[1]);
        //删除视频文件和视频文件
        Json::Value video;
        if(!tb_video->SelectOne(video_id, &video))
        {
          //获取数据库数据失败
          rsp.status = 500;
          rsp.body = R"({"result":false, "reason":获取数据库数据失败})";
          rsp.set_header("Content-Type","application/json");
          return;
        }
        std::string video_path = WWWROOT;
        video_path += video["video"].asString();
        std::string image_path = WWWROOT;
        image_path += video["image"].asString();
        remove(video_path.c_str());
        remove(image_path.c_str());
        //删除数据库信息
        if(!tb_video->Delete(video_id))
        {
          //删除数据库数据失败
          rsp.status = 500;
          rsp.body = R"({"result":false, "reason":删除数据库数据失败})";
          rsp.set_header("Content-Type","application/json");
          return;
        } 
        return;
      }
      static void Update(const httplib::Request &req, httplib::Response &rsp)
      {
        //获取要修改的视频id已经修改后的信息
        int video_id = std::stoi(req.matches[1]);
        Json::Value video;
        if(!JsonUtil::Deserialize(req.body,&video))
        {
          //反序列化失败
          rsp.status = 500;
          rsp.body = R"({"result":false, "reason":反序列化失败})";
          rsp.set_header("Content-Type","application/json");
          return;
        } 
        //修改数据库数据
        if(!tb_video->Update(video_id,video))
        {
          //修改数据库数据失败
          rsp.status = 500;
          rsp.body = R"({"result":false, "reason":修改数据库数据失败})";
          rsp.set_header("Content-Type","application/json");
          return;
        } 
        return;
      }
      static void SelectOne(const httplib::Request &req, httplib::Response &rsp)
      {
        //获取视频id
        int video_id = std::stoi(req.matches[1]);
        //在数据库查询指定信息
        Json::Value video;
        if(!tb_video->SelectOne(video_id, &video))
        {
          //查询单个数据库数据失败
          rsp.status = 500;
          rsp.body = R"({"result":false, "reason":查询单个数据失败})";
          rsp.set_header("Content-Type","application/json");
          return;
        } 
        //组织响应正文
        JsonUtil::Serialize(video,&rsp.body);
        rsp.set_header("Content-Type", "application/json");
        return;
      }
      static void SelectAll(const httplib::Request &req, httplib::Response &rsp)
      {
        //有查询所有信息 也有是模糊查询
        //所以要获取查询字符串 有则是模糊查询
        Json::Value videos;
        if(!req.has_param("search"))
        {
          //没有search则是查询所有信息
          if(!tb_video->SelectAll(&videos))
          {
            //查询所有数据库数据失败
            rsp.status = 500;
            rsp.body = R"({"result":false, "reason":查询所有数据库数据失败})";
            rsp.set_header("Content-Type","application/json");
            return;
          } 
          //组织响应正文
          JsonUtil::Serialize(videos,&rsp.body);
          rsp.set_header("Content-Type", "application/json");
          return;
        }
        //模糊查询
        std::string search_key;
        search_key = req.get_param_value("search_key");
        if(!tb_video->SelectLike(search_key,&videos))
        {
          //模糊查询数据库数据失败
          rsp.status = 500;
          rsp.body = R"({"result":false, "reason":模糊查询数据库数据失败})";
          rsp.set_header("Content-Type","application/json");
          return;
        } 
        //组织响应正文
        JsonUtil::Serialize(videos,&rsp.body);
        rsp.set_header("Content-Type", "application/json");
        return;
      }

    public:
      Server(int port):_port(port){}
      bool RunModule()
      {
        //初始化数据管理模块 创建指定的目录用于保存数据
        tb_video = new TableVideo();

        FileUtil(WWWROOT).CreateDirectory();
        std::string video_real_path;// ./www/video/
        std::string image_real_path;// ./www/image/
        video_real_path += WWWROOT;
        video_real_path += VIDEO_ROOT;
        FileUtil(video_real_path).CreateDirectory();
        image_real_path += WWWROOT;
        image_real_path += IMAGE_ROOT;
        FileUtil(image_real_path).CreateDirectory();

        //搭建http服务器 并初始化根目录和函数映射表
        //    设置静态根目录
        _srv.set_mount_point("/", WWWROOT);
        //    添加关键字和函数的映射关系
        _srv.Post("/video", Insert);
        _srv.Delete("/video/(\\d+)", Delete);
        _srv.Put("/video/(\\d+)", Update);
        _srv.Get("/video/(\\d+)", SelectOne);
        _srv.Get("/video", SelectAll);
        //启动服务器
        std::cout << "server is ready" << std::endl;
        _srv.listen("0.0.0.0",_port);

        return true;
      }
  };
}










#endif
